/*
 * 文件名：BucketPath.java
 * 版权：亚信联创版权所有
 * 描述：TODO
 * 修改人：napo
 * 修改时间：2015-1-14
 * 修改内容：TODO
 */
package com.ailk.bigdata.etl.realstream.server.service.impl;

import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Enumeration;
import java.util.TimeZone;
import java.util.concurrent.atomic.AtomicLong;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.google.common.base.Preconditions;

/**
 * @description 文件命名实现类
 * @author [xuwei3]
 * @version [版本号,2015-1-14]
 * @see [相关类/方法]
 * @since [产品/模块版本]
 */
public class FilePathFormatUtil
{
	final public static String TAG_REGEX = "\\%(\\w|\\%)|\\%\\{([\\w\\.-]+)\\}";
	final public static Pattern tagPattern = Pattern.compile(TAG_REGEX);
	public static String localHost;

	protected static String replaceShorthand(char c, boolean needRounding, int unit, int roundDown, long ts)
	{
		String timestampHeader = null;
		timestampHeader = String.valueOf(ts);
		if (needRounding)
		{
			ts = roundDown(roundDown, unit, ts);
		}
		String formatString = "";
		switch (c)
		{
			case '%':
				return "%";
			case 'a':
				formatString = "EEE";
				break;
			case 'A':
				formatString = "EEEE";
				break;
			case 'b':
				formatString = "MMM";
				break;
			case 'B':
				formatString = "MMMM";
				break;
			case 'c':
				formatString = "EEE MMM d HH:mm:ss yyyy";
				break;
			case 'd':
				formatString = "dd";
				break;
			case 'D':
				formatString = "MM/dd/yy";
				break;
			case 'H':
				formatString = "HH";
				break;
			case 'h':
				if (null == localHost)
				{
					localHost = getIPAddress();
				}
				return localHost;
			case 'I':
				formatString = "hh";
				break;
			case 'i':
				return System.getProperty("client_id", "");
			case 'j':
				formatString = "DDD";
				break;
			case 'k':
				formatString = "H";
				break;
			case 'l':
				formatString = "h";
				break;
			case 'm':
				formatString = "MM";
				break;
			case 'M':
				formatString = "mm";
				break;
			case 'N':
				return "" + (ts / 1000);
			case 'p':
				formatString = "a";
				break;
			case 's':
				return "" + (ts / 1000);
			case 'S':
				formatString = "ss";
				break;
			case 't':
				return timestampHeader;
			case 'y':
				formatString = "yy";
				break;
			case 'Y':
				formatString = "yyyy";
				break;
			case 'z':
				formatString = "ZZZ";
				break;
			default:
				return "";
		}
		SimpleDateFormat format = new SimpleDateFormat(formatString);
		format.setTimeZone(TimeZone.getDefault());
		Date date = new Date(ts);
		return format.format(date);
	}

	private static long roundDown(int roundDown, int unit, long ts)
	{
		long timestamp = ts;
		if (roundDown <= 0)
		{
			roundDown = 1;
		}
		switch (unit)
		{
			case Calendar.SECOND:
				timestamp = roundDownTimeStampSeconds(ts, roundDown);
				break;
			case Calendar.MINUTE:
				timestamp = roundDownTimeStampMinutes(ts, roundDown);
				break;
			case Calendar.HOUR_OF_DAY:
				timestamp = roundDownTimeStampHours(ts, roundDown);
				break;
			default:
				timestamp = ts;
				break;
		}
		return timestamp;
	}

	public static String escapeString(String in, boolean needRounding, int unit, int roundDown)
	{
		long ts = System.currentTimeMillis();
		Matcher matcher = tagPattern.matcher(in);
		StringBuffer sb = new StringBuffer();
		while (matcher.find())
		{
			String replacement = "";
			Preconditions.checkState(matcher.group(1) != null && matcher.group(1).length() == 1, "Expected to match single character tag in string "
					+ in);
			char c = matcher.group(1).charAt(0);
			replacement = replaceShorthand(c, needRounding, unit, roundDown, ts);

			replacement = replacement.replaceAll("\\\\", "\\\\\\\\");
			replacement = replacement.replaceAll("\\$", "\\\\\\$");

			matcher.appendReplacement(sb, replacement);
		}
		matcher.appendTail(sb);
		return sb.toString();
	}

	public static long roundDownTimeStampSeconds(long timestamp, int roundDownSec) throws IllegalStateException
	{
		Preconditions.checkArgument(roundDownSec > 0 && roundDownSec <= 60, "RoundDownSec must be > 0 and <=60");
		Calendar cal = roundDownField(timestamp, Calendar.SECOND, roundDownSec);
		cal.set(Calendar.MILLISECOND, 0);
		return cal.getTimeInMillis();
	}

	public static long roundDownTimeStampMinutes(long timestamp, int roundDownMins) throws IllegalStateException
	{
		Preconditions.checkArgument(roundDownMins > 0 && roundDownMins <= 60, "RoundDown must be > 0 and <=60");
		Calendar cal = roundDownField(timestamp, Calendar.MINUTE, roundDownMins);
		cal.set(Calendar.SECOND, 0);
		cal.set(Calendar.MILLISECOND, 0);
		return cal.getTimeInMillis();

	}

	public static long roundDownTimeStampHours(long timestamp, int roundDownHours) throws IllegalStateException
	{
		Preconditions.checkArgument(roundDownHours > 0 && roundDownHours <= 24, "RoundDown must be > 0 and <=24");
		Calendar cal = roundDownField(timestamp, Calendar.HOUR_OF_DAY, roundDownHours);
		cal.set(Calendar.MINUTE, 0);
		cal.set(Calendar.SECOND, 0);
		cal.set(Calendar.MILLISECOND, 0);
		return cal.getTimeInMillis();
	}

	private static Calendar roundDownField(long timestamp, int field, int roundDown)
	{
		Preconditions.checkArgument(timestamp > 0, "Timestamp must be positive");
		Calendar cal = Calendar.getInstance();
		cal.setTimeInMillis(timestamp);
		int fieldVal = cal.get(field);
		int remainder = (fieldVal % roundDown);
		cal.set(field, fieldVal - remainder);
		return cal;
	}

	public static String getIPAddress()
	{

		Enumeration<?> allNetInterfaces = null;
		try
		{
			allNetInterfaces = NetworkInterface.getNetworkInterfaces();
		}
		catch (SocketException e)
		{
		}
		InetAddress ip = null;
		while (allNetInterfaces != null && allNetInterfaces.hasMoreElements())
		{
			NetworkInterface netInterface = (NetworkInterface) allNetInterfaces.nextElement();
			Enumeration<?> addresses = netInterface.getInetAddresses();
			while (addresses.hasMoreElements())
			{
				ip = (InetAddress) addresses.nextElement();
				if (ip != null && ip instanceof Inet4Address)
				{
					return ip.getHostAddress();
				}
			}
		}
		return "";
	}

	public static void main(String[] args)
	{
		System.setProperty("client_id", "01");
		// System.out.println(String.format("%06d", 1));
		String realFile = FilePathFormatUtil.escapeString("/path/buffer_file/%Y%m%d/%H", true, Calendar.HOUR_OF_DAY, 1);
		// System.out.println(realFile);

		realFile = FilePathFormatUtil.escapeString("A94002%Y%m%d%H%M%%02d%i.dat", true, Calendar.MINUTE, 5);
		System.out.println(realFile);
		System.out.println(String.format(realFile, 1));

		AtomicLong fileExtensionCounter = new AtomicLong(0);
		System.out.println(fileExtensionCounter.incrementAndGet());

	}
}
